import $ from 'jquery';
import SimpleModule from './Module';
import Popover from './Popover';
import Toolbar from './Toolbar';
import Selection from './Selection';
import Button from './buttons/Button';
import BoldButton from './buttons/BoldButton';
import ItalicButton from './buttons/ItalicButton';
import UnderlineButton from './buttons/UnderlineButton';
import StrikethroughButton from './buttons/StrikethroughButton';
import AlignmentButton from './buttons/AlignmentButton';
import ImageButton from './buttons/ImageButton';
import OrderListButton from './buttons/OrderListButton';
import UnorderListButton from './buttons/UnorderListButton';
import BlockquoteButton from './buttons/BlockquoteButton';
import CodeButton from './buttons/CodeButton';
import LinkButton from './buttons/LinkButton';
import IndentButton from './buttons/IndentButton';
import TableButton from './buttons/TableButton';
import OutdentButton from './buttons/OutdentButton';
import ColorButton from './buttons/ColorButton';
import TitleButton from './buttons/TitleButton';
import FontScaleButton from './buttons/FontScaleButton';
import HrButton from './buttons/HrButton';
import FullScreenButton from './buttons/FullScreenButton';

import Indentation from './Indentation';
import Keystroke from './Keystroke';
import Clipboard from './Clipboard';
import Formatter from './Formatter';
import Util from './Util';
import UndoManager from './UndoManager';
import InputManager from './InputManager';

import hotKeys from './hotkeys';
import uploader from './uploader';


class Simditor extends SimpleModule {
    
    _init() {
        let editor, form, uploadOpts;
        this.textarea = $(this.opts.textarea);
        this.opts.placeholder = this.opts.placeholder || this.textarea.attr('placeholder');
        if (!this.textarea.length) throw new Error('simditor: param textarea is required.');

        editor = this.textarea.data('simditor');
        if (editor != null) editor.destroy();

        this.id = ++Simditor.count;
        this._render();
        if (hotKeys) {
            this.hotkeys = hotKeys({ el: this.body });
        } else {
            throw new Error('simditor: simple-hotkeys is required.');
        }
        if (this.opts.upload && uploader) {
            uploadOpts = typeof this.opts.upload === 'object' ? this.opts.upload : {};
            this.uploader = uploader(uploadOpts);
        }
        form = this.textarea.closest('form');
        if (form.length) {
            form.on(`submit.simditor-${this.id}`, ((_this => () => _this.sync()))(this));
            form.on(`reset.simditor-${this.id}`, ((_this => () => _this.setValue('')))(this));
        }
        this.on('initialized', (() => {
            if (this.opts.placeholder) {
                this.on('valuechanged', () => this._placeholder());
            }
            this.setValue(this.textarea.val().trim() || '');
            if (this.textarea.attr('autofocus')) {
                return this.focus();
            }
        }));
        if (this.util.browser.mozilla) {
            this.util.reflow();
            try {
                document.execCommand('enableObjectResizing', false, false);
                return document.execCommand('enableInlineTableEditing', false, false);
            } catch (_error) {
                _error;
            }
        }
    }

    _render() {
        let key, ref, results;
        this.el = $(this._tpl).insertBefore(this.textarea);
        this.wrapper = this.el.find('.simditor-wrapper');
        this.body = this.wrapper.find('.simditor-body');
        this.placeholderEl = this.wrapper.find('.simditor-placeholder').append(this.opts.placeholder);
        this.el.data('simditor', this);
        this.wrapper.append(this.textarea);
        this.textarea.data('simditor', this).blur();
        this.body.attr('tabindex', this.textarea.attr('tabindex'));

        if (this.util.os.mac) this.el.addClass('simditor-mac');
        if (this.util.os.linux) this.el.addClass('simditor-linux');
        if (this.util.os.mobile) this.el.addClass('simditor-mobile');

        if (this.opts.params) {
            ref = this.opts.params;
            results = [];
            for (key in ref)
                results.push($(`<input type='hidden' name='${key}' value='${ref[key]}'/>`).insertAfter(this.textarea));
            return results;
        }
    }

    _placeholder() {
        let children;
        children = this.body.children();
        if (children.length === 0 || (children.length === 1 && this.util.isEmptyNode(children) && parseInt(children.css('margin-left') || 0) < this.opts.indentWidth)) {
            return this.placeholderEl.show();
        } else {
            return this.placeholderEl.hide();
        }
    }

    setValue(val) {
        this.hidePopover();
        this.textarea.val(val);
        this.body.get(0).innerHTML = val;
        this.formatter.format();
        this.formatter.decorate();
        this.util.reflow(this.body);
        this.inputManager.lastCaretPosition = null;
        return this.trigger('valuechanged');
    }

    getValue() {
        return this.sync();
    }

    sync() {
        let children;
        let cloneBody;
        let emptyP;
        let firstP;
        let lastP;
        let val;
        cloneBody = this.body.clone();
        this.formatter.undecorate(cloneBody);
        this.formatter.format(cloneBody);
        this.formatter.autolink(cloneBody);
        children = cloneBody.children();
        lastP = children.last('p');
        firstP = children.first('p');
        while (lastP.is('p') && this.util.isEmptyNode(lastP)) {
            emptyP = lastP;
            lastP = lastP.prev('p');
            emptyP.remove();
        }
        while (firstP.is('p') && this.util.isEmptyNode(firstP)) {
            emptyP = firstP;
            firstP = lastP.next('p');
            emptyP.remove();
        }
        cloneBody.find('img.uploading').remove();
        val = $.trim(cloneBody.html());
        this.textarea.val(val);
        return val;
    }

    focus() {
        let $blockEl;
        let range;
        if (!(this.body.is(':visible') && this.body.is('[contenteditable]'))) {
            this.el.find('textarea:visible').focus();
            return;
        }
        if (this.inputManager.lastCaretPosition) {
            this.undoManager.caretPosition(this.inputManager.lastCaretPosition);
            return this.inputManager.lastCaretPosition = null;
        } else {
            $blockEl = this.body.children().last();
            if (!$blockEl.is('p')) {
                $blockEl = $('<p/>').append(this.util.phBr).appendTo(this.body);
            }
            range = document.createRange();
            return this.selection.setRangeAtEndOf($blockEl, range);
        }
    }

    blur() {
        if (this.body.is(':visible') && this.body.is('[contenteditable]')) {
            return this.body.blur();
        } else {
            return this.body.find('textarea:visible').blur();
        }
    }

    hidePopover() {
        return this.el.find('.simditor-popover').each((i, popover) => {
            popover = $(popover).data('popover');
            if (popover.active) {
                return popover.hide();
            }
        });
    }

    destroy() {
        this.triggerHandler('destroy');
        this.textarea.closest('form').off(`.simditor .simditor-${this.id}`);
        this.selection.clear();
        this.inputManager.focused = false;
        this.textarea.insertBefore(this.el).hide().val('').removeData('simditor');
        this.el.remove();
        $(document).off(`.simditor-${this.id}`);
        $(window).off(`.simditor-${this.id}`);
        return this.off();
    }
}
Simditor.prototype.opts = {
    textarea: null,
    placeholder: '',
    defaultImage: require("../images/image.png"),
    params: {},
    upload: false,
    indentWidth: 40
};
Simditor.prototype._tpl = `
<div class="simditor">
  <div class="simditor-wrapper">
    <div class="simditor-placeholder"></div>
    <div class="simditor-body" contenteditable="true">
    </div>
  </div>
</div>
`;
Simditor.Button = Button;
Simditor.Popover = Popover;
Simditor.i18n = {
    'zh-CN': {
        'blockquote': '引用',
        'bold': '加粗文字',
        'code': '插入代码',
        'color': '文字颜色',
        'coloredText': '彩色文字',
        'hr': '分隔线',
        'image': '插入图片',
        'externalImage': '外链图片',
        'uploadImage': '上传图片',
        'uploadFailed': '上传失败了',
        'uploadError': '上传出错了',
        'imageUrl': '图片地址',
        'imageSize': '图片尺寸',
        'imageAlt': '图片描述',
        'restoreImageSize': '还原图片尺寸',
        'uploading': '正在上传',
        'indent': '向右缩进',
        'outdent': '向左缩进',
        'italic': '斜体文字',
        'link': '插入链接',
        'linkText': '链接文字',
        'linkUrl': '链接地址',
        'linkTarget': '打开方式',
        'openLinkInCurrentWindow': '在新窗口中打开',
        'openLinkInNewWindow': '在当前窗口中打开',
        'removeLink': '移除链接',
        'ol': '有序列表',
        'ul': '无序列表',
        'strikethrough': '删除线文字',
        'table': '表格',
        'deleteRow': '删除行',
        'insertRowAbove': '在上面插入行',
        'insertRowBelow': '在下面插入行',
        'deleteColumn': '删除列',
        'insertColumnLeft': '在左边插入列',
        'insertColumnRight': '在右边插入列',
        'deleteTable': '删除表格',
        'title': '标题',
        'normalText': '普通文本',
        'underline': '下划线文字',
        'alignment': '水平对齐',
        'alignCenter': '居中',
        'alignLeft': '居左',
        'alignRight': '居右',
        'selectLanguage': '选择程序语言',
        'fontScale': '字体大小',
        'fontScaleXLarge': '超大字体',
        'fontScaleLarge': '大号字体',
        'fontScaleNormal': '正常大小',
        'fontScaleSmall': '小号字体',
        'fontScaleXSmall': '超小字体'
    },
    'en-US': {
        'blockquote': 'Block Quote',
        'bold': 'Bold',
        'code': 'Code',
        'color': 'Text Color',
        'coloredText': 'Colored Text',
        'hr': 'Horizontal Line',
        'image': 'Insert Image',
        'externalImage': 'External Image',
        'uploadImage': 'Upload Image',
        'uploadFailed': 'Upload failed',
        'uploadError': 'Error occurs during upload',
        'imageUrl': 'Url',
        'imageSize': 'Size',
        'imageAlt': 'Alt',
        'restoreImageSize': 'Restore Origin Size',
        'uploading': 'Uploading',
        'indent': 'Indent',
        'outdent': 'Outdent',
        'italic': 'Italic',
        'link': 'Insert Link',
        'linkText': 'Text',
        'linkUrl': 'Url',
        'linkTarget': 'Target',
        'openLinkInCurrentWindow': 'Open link in current window',
        'openLinkInNewWindow': 'Open link in new window',
        'removeLink': 'Remove Link',
        'ol': 'Ordered List',
        'ul': 'Unordered List',
        'strikethrough': 'Strikethrough',
        'table': 'Table',
        'deleteRow': 'Delete Row',
        'insertRowAbove': 'Insert Row Above',
        'insertRowBelow': 'Insert Row Below',
        'deleteColumn': 'Delete Column',
        'insertColumnLeft': 'Insert Column Left',
        'insertColumnRight': 'Insert Column Right',
        'deleteTable': 'Delete Table',
        'title': 'Title',
        'normalText': 'Text',
        'underline': 'Underline',
        'alignment': 'Alignment',
        'alignCenter': 'Align Center',
        'alignLeft': 'Align Left',
        'alignRight': 'Align Right',
        'selectLanguage': 'Select Language',
        'fontScale': 'Font Size',
        'fontScaleXLarge': 'X Large Size',
        'fontScaleLarge': 'Large Size',
        'fontScaleNormal': 'Normal Size',
        'fontScaleSmall': 'Small Size',
        'fontScaleXSmall': 'X Small Size'
    }
}
Simditor.connect(Util);
Simditor.connect(InputManager);
Simditor.connect(Selection);
Simditor.connect(UndoManager);
Simditor.connect(Keystroke);
Simditor.connect(Formatter);
Simditor.connect(Toolbar);
Simditor.connect(Indentation);
Simditor.connect(Clipboard);
Simditor.count = 0;
Simditor.Toolbar.addButton(TitleButton);
Simditor.Toolbar.addButton(FontScaleButton);
Simditor.Toolbar.addButton(BoldButton);
Simditor.Toolbar.addButton(ItalicButton);
Simditor.Toolbar.addButton(UnderlineButton);
Simditor.Toolbar.addButton(ColorButton);
Simditor.Toolbar.addButton(OrderListButton);
Simditor.Toolbar.addButton(UnorderListButton);
Simditor.Toolbar.addButton(BlockquoteButton);
Simditor.Toolbar.addButton(CodeButton);
Simditor.Toolbar.addButton(LinkButton);
Simditor.Toolbar.addButton(ImageButton);
Simditor.Toolbar.addButton(IndentButton);
Simditor.Toolbar.addButton(OutdentButton);
Simditor.Toolbar.addButton(HrButton);
Simditor.Toolbar.addButton(TableButton);
Simditor.Toolbar.addButton(StrikethroughButton);
Simditor.Toolbar.addButton(AlignmentButton);
Simditor.Toolbar.addButton(FullScreenButton);
export default Simditor;